package com.ssm.changeunit.command;

import com.ssm.changeunit.*;
import com.ssm.changeunit.diff.ContentMerger;
import com.ssm.changeunit.persistance.PersistanceException;
import com.ssm.changeunit.persistance.DatabaseManager;
import com.ssm.changeunit.persistance.ManagedChangeUnitDAO;
import com.ssm.changeunit.persistance.ManagedChangeUnitDTO;
import com.ssm.changeunit.persistance.ManagedItemListDAO;
import com.ssm.changeunit.persistance.ManagedItemListDTO;
import com.ssm.changeunit.util.FileUtil;
import java.io.IOException;
import java.util.List;
import org.apache.log4j.Logger;

/**
 *
 * @author 시리우스
 */
public class UpdateCommandWorker extends CommandWorker {
    private Logger log = Logger.getLogger(UpdateCommandWorker.class);
    
    @Override
    public void work(CommandWorkerOptions commandWorkerOptions) throws CommandWorkerException {
        // 데이터베이스 체크
        log.debug("데이터베이스가 존재하는지 검사합니다.");
        
        try {
            if(!DatabaseManager.getInstance().isExists())
                throw new CommandWorkerException("데이터베이스가 존재하지 않습니다.");
        }
        catch(PersistanceException ex) {
            throw new CommandWorkerException(ex);
        }
        
        try {
            // 현재 작성하는 ChangeUnitID와, Branch의 ChangeUnit이 다른지 검사합니다.
            ManagedChangeUnitDTO managedChangeUnitDTO = new ManagedChangeUnitDAO().find();
            
            Branch currentBranch = new BranchFactory().createProduct(Environment.getCurrentBranch());
            
            String managedChangeUnitId = managedChangeUnitDTO.getManagedChangeUnitId();
            String currentChangeUnitId = currentBranch.getCurrentChangeUnit().getChangeUnitId();
            
            // 같다면..
            if(managedChangeUnitId.equals(currentChangeUnitId)) {
                log.debug("ManagedChangeUnitId: " + managedChangeUnitId + " == CurrentChangeUnitId: " + currentChangeUnitId);
                
                throw new CommandWorkerException("Update할 필요가 없습니다.");
            }
            else {
                log.debug("ManagedChangeUnitId: " + managedChangeUnitId + " != CurrentChangeUnitId: " + currentChangeUnitId);
                
                log.info("Update를 수행합니다.");
                
                // Target이 되는 ChangeUnit을 가져옵니다.
                ChangeUnit currentChangeUnit = currentBranch.getCurrentChangeUnit();
                
                // Current ChangeUnit에서 관리하는 ChangeUnit을 가져옵니다.
                List<ChangeUnitItem> changeUnitItems = currentChangeUnit.getChangeUnitItems();
                
                // Local의 파일 정보를 가져옵니다.
                List<ManagedItemListDTO> managedItemLists = new ManagedItemListDAO().list();
                
                log.debug("Local에서 관리되는 파일 리스트");
                
                for(ManagedItemListDTO managedItemListDTO : managedItemLists) {
                    String managedFilePath = managedItemListDTO.getFilePath();
                    
                    log.debug("-> " + managedFilePath);
                    
                    log.debug("CurrentChangeUnit에서 " + managedFilePath +"를 찾습니다.");
                    
                    for(ChangeUnitItem changeUnitItem : changeUnitItems) {
                        String changeUnitItemFilePath = changeUnitItem.getFilePath();
                        
                        if(managedFilePath.equals(changeUnitItemFilePath)) {
                            log.debug("파일을 찾았습니다.");
                            
                            // 여기서 비교를한 후에..
                            // 파일에 다시 기록해야한다..
                            
                            log.debug("내용을 비교합니다..");
                            
                            ContentMerger contentMerge = new ContentMerger();
                            
                            String originContent = FileUtil.readFromFile(Environment.ROOT_DIR + changeUnitItemFilePath);
                            String targetContent = new String(changeUnitItem.getRefChangeLog().getContent());
                            
                            String[] newContentArray = contentMerge.merge(originContent.split("\n"), targetContent.split("\n"));
                            
                            StringBuilder newContentBuilder = new StringBuilder();
                            
                            for(String line : newContentArray) {
                                log.debug("-> " + line);
                                
                                newContentBuilder.append(line + "\r\n");
                            }
                            
                            // 파일에 기록합니다.
                            log.debug("파일에 기록합니다.");
                            FileUtil.saveDataToFile(changeUnitItemFilePath, newContentBuilder.toString());
                            
                            break;
                        }
                    }
                }
                
                log.debug("Local에서 관리되는 파일 리스트 끝.");
                
                ManagedItemListFactory managedItemListFactory = new ManagedItemListFactory();
                
                // 서버의 새 파일도 가져와서 기록해야한다.
                for(ChangeUnitItem changeUnitItem : changeUnitItems) {
                    String changeUnitItemFilePath = changeUnitItem.getFilePath();
                    
                    log.debug("-> " + changeUnitItemFilePath);
                    
                    log.debug("ManagedItemList에서 " + changeUnitItemFilePath +"를 찾습니다.");
                    
                    for(ManagedItemListDTO managedItemListDTO : managedItemLists) {
                        String managedFilePath = managedItemListDTO.getFilePath();
                        
                        if(!managedFilePath.equals(changeUnitItemFilePath)) {
                            log.debug("파일을 찾을 수 없습니다. 새로운 파일입니다.");
                            
                            // 로컬 파일에 기록해야한다.
                            FileUtil.saveDataToFile(changeUnitItemFilePath, new String(changeUnitItem.getRefChangeLog().getContent()));
                            
                            // ManagedItemList에 추가..
                            managedItemListFactory.createProduct(changeUnitItemFilePath);
                            
                            break;
                        }
                    }
                }                
                
                // 현재 작성하는 ChangeUnitID와, Branch의 ChangeUnit이 다른지 검사합니다.
                managedChangeUnitDTO.setManagedChangeUnitId(currentChangeUnitId);
                new ManagedChangeUnitDAO().update(managedChangeUnitDTO);
            }
        }
        catch(IOException ex) {
            throw new CommandWorkerException(ex);
        }
        catch(CreateException ex) {
            throw new CommandWorkerException(ex);
        }
        catch(PersistanceException ex) {
            throw new CommandWorkerException(ex);
        }
    }
}
